package com.fs.schedule;

import com.alibaba.fastjson.JSON;
import com.aliyun.dysmsapi20170525.Client;
import com.fs.global.config.CustomConfig;
import com.fs.service.DeviceOperationService;
import com.fs.service.PurchaseService;
import com.fs.service.ScheduledTaskService;
import com.fs.service.WxPayService;
import com.fs.service.bo.purchase.BoPurchase;
import com.fs.service.bo.purchase.Status;
import com.fs.service.bo.task.BoTask;
import lombok.Getter;
import lombok.extern.log4j.Log4j2;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;

import java.util.*;

import com.aliyun.dysmsapi20170525.models.*;
import com.aliyun.teaopenapi.models.*;

import javax.annotation.PostConstruct;

@Component
@Log4j2
public class ScheduleTool {
    private final DeviceOperationService deviceOperation;
    private final CustomConfig customConfig;
    private final ScheduledTaskService taskService;
    private final ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
    private final WxPayService wxPayService;
    private final PurchaseService purchaseService;

    public ScheduleTool(DeviceOperationService deviceOperation, CustomConfig config, ScheduledTaskService taskService, WxPayService wxPayService, PurchaseService purchaseService) {
        this.deviceOperation = deviceOperation;
        this.customConfig = config;
        this.taskService = taskService;
        this.wxPayService = wxPayService;
        this.purchaseService = purchaseService;
        scheduler.initialize();
    }

    @PostConstruct
    public void loadTask() {
        List<BoTask> tasks = taskService.getTasks();
        tasks.forEach(task -> {
            if (task.getType().equals(ScheduledTaskService.NOTIFY)) {
                NotifyCleanTask cleanTask = JSON.parseObject(task.getContent(), NotifyCleanTask.class);
                if (cleanTask.getDate().after(new Date()))
                    addNotifyTask(cleanTask);
            } else if (task.getType().equals(ScheduledTaskService.CUT_POWER)) {
                CutPowerTask cutPowerTask = JSON.parseObject(task.getContent(), CutPowerTask.class);
                if (cutPowerTask.getDate().after(new Date()))
                    addCutPowerTask(cutPowerTask);
            }
        });

        List<BoPurchase> lockedPurchase = purchaseService.getLockedPurchase();
        lockedPurchase.forEach(purchase -> {
            Date expiredTime = new Date(new Date().getTime() + 60000);
            addCloseWxOrderTask(purchase.getTradeNo(), expiredTime);
        });
    }

    public void addNotifyTask(NotifyCleanTask taskInfo) {
        Runnable notifyTask = () -> {
            Config config = new Config()
                    .setAccessKeyId(customConfig.getAliAccessKeyId())
                    .setAccessKeySecret(customConfig.getAliAccessKeySecret())
                    .setEndpoint("dysmsapi.aliyuncs.com");
            try {
                Client client = new Client(config);
                SendSmsRequest sms = new SendSmsRequest();
                sms.setSignName(customConfig.getAliSignName());
                sms.setTemplateCode(customConfig.getAliTemplateCode());
                sms.setPhoneNumbers(taskInfo.getPhoneNumbers());
                String template = String.format("{\"room\":\"%s\",\"time\":\"%s\"}", taskInfo.getRoomName(), taskInfo.getCleanTime());
                sms.setTemplateParam(template);
                client.sendSms(sms);
            } catch (Exception e) {
                e.printStackTrace();
                log.error("调用阿里云短信sdk异常");
                return;
            }
            taskService.removeTask(taskInfo.getId());
            log.info("发送短信");
        };

        scheduler.schedule(notifyTask, taskInfo.getDate());
        taskService.addTask(taskInfo.getId(), ScheduledTaskService.NOTIFY, JSON.toJSONString(taskInfo));
    }

    public void addCutPowerTask(CutPowerTask taskInfo) {
        Runnable task = () -> {
            try {
                deviceOperation.closeSwitches(taskInfo.getSwitchIds());
            } catch (Exception e) {
                e.printStackTrace();
                log.error("关闭电闸失败");
            } finally {
                taskService.removeTask(taskInfo.getId());
            }
            log.info("切断电源");
        };

        taskService.addTask(taskInfo.getId(), ScheduledTaskService.CUT_POWER, JSON.toJSONString(taskInfo));
        scheduler.schedule(task, taskInfo.getDate());
    }

    public void addCloseWxOrderTask(String outTradeNo, Date date) {
        Runnable task = () -> {
            BoPurchase purchase = purchaseService.getPurchaseByTradeNo(outTradeNo);
            try {
                if (purchase.getState() == Status.NotPayed || purchase.getState() == Status.Expired) {
                    wxPayService.closePurchase(outTradeNo);
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.error(e.getMessage());
            }
            purchaseService.unLockPurchase(outTradeNo);
        };
        scheduler.schedule(task, date);
    }

    @Getter
    public static class NotifyCleanTask {
        private final String id;
        private final Date date;
        private final String roomName;
        private final String cleanTime;
        private final String phoneNumbers;

        public NotifyCleanTask(Date date, String roomName, String cleanTime, List<String> phones) {
            id = UUID.randomUUID().toString();
            this.date = date;
            this.roomName = roomName;
            this.cleanTime = cleanTime;
            this.phoneNumbers = String.join(",", phones);
        }
    }

    @Getter
    public static class CutPowerTask {
        private final String id;
        private final Date date;
        private final List<Integer> switchIds;

        public CutPowerTask(Date date, List<Integer> switchIds) {
            id = UUID.randomUUID().toString();
            this.date = date;
            this.switchIds = switchIds;
        }

    }

}
